package com.xuecheng.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.xuecheng.commons.model.vo.AuthInfo;
import com.xuecheng.commons.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URLEncoder;

/**
 * 全局过滤器
 * 1、交给容器管理
 * 2、实现两个接口
 * 3、实现内部的两个方法
 * 4、在filter方法中，完成核心业务逻辑
 */
@Component
@Slf4j
public class AuthFilter implements GlobalFilter, Ordered {

    /**
     * 核心方法：完成登录校验
     * exchange：请求上下文
     * 获取请求的对象和响应的对象
     * chain：过滤器链
     * 放行，向下执行
     */
    @SneakyThrows
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //1、排除不需要验证的请求路径，放行
        //1.1 获取当前请求的连接
        String path = request.getURI().getPath();
        log.info("请求的path={}", path);
        //1.2 判断是否需要进行验证
        if (path.contains("coursePub/preview") ||
                path.contains("auth/login") ||
                path.contains("basic/dictionary") ||
                path.contains("category/tree-nodes") ||
                path.contains("course/upload") ||
                path.contains("search/")) {
            return chain.filter(exchange);
        }
        //2、获取请求头中的token
        String token = request.getHeaders().getFirst("Authorization");
        log.info("请求token={}", token);
        //3、验证token有效性
        Boolean verifyToken = JwtUtils.verifyToken(token); //返回true，表示以登录
        //4、如果token失效，返回响应401
        if (!verifyToken) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete(); //返回响应
        }
        //5、如果token有效，放行
        //5.1 解析token，获取token中的userId,companyId,companyName
        Claims claims = JwtUtils.parserToken(token).getBody();
        Long userId = claims.get("userId", Long.class);
        Long companyId = claims.get("companyId", Long.class);
        String name = claims.get("companyName", String.class);
        //5.2 构造java对象。认证对象
        AuthInfo info = new AuthInfo();
        info.setUid(userId);
        info.setCompanyId(companyId);
        info.setCompanyName(name);
        //5.3 写入到请求头中
        String json = URLEncoder.encode(JSON.toJSONString(info), "utf-8");
//        String json = JSON.toJSONString(info);

        ServerHttpRequest httpRequest = request.mutate().headers(httpHeaders -> {
            httpHeaders.set("payload", json);
        }).build();
        exchange.mutate().request(httpRequest);
        return chain.filter(exchange);
    }

    //过滤器的优先级
    public int getOrder() {
        return 0;
    }
}